home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-13 | 10.0 KB | 363 lines | [TEXT/MSET] |
- \ Nov 95 JRF added EraseRect call to Draw: method to fix a caret problem
- \ when using outline highliting.
- \ 30May93 MRH optimized KEY: to only call fixPanRect: when necessary
-
- \ 15May93 DBH removed noclip from CallTEScroll: per mrh.
- \ Use selstart: and getpoint: in CARETLOC: . Deleted CURRENTLINE: method.
- \ Added lineEnd: method.
-
- \ 17Jun93 mrh removed update: in setSelect: - don't need it
- \ Sept 93 mrh revised for Control now being a View subclass
- \ May 94 mrh using LeftMargin instead of offsetting MainView. Handling
- \ cursor change here instead of in TextEdit - our view system
- \ makes it easy.
-
- need window+
- need TextEdit
-
- 4 constant LeftMargin \ White space at left of the text
- 20 constant BottomMargin \ (was 40 JRF) White space at the bottom
-
- \ 0 value ThisTE
-
- \ false value chkScroll?
-
- objptr $TMP class_is string+
-
-
- :class TEScroller super{ scroller }
-
- TextEdit theTE
- rect rPanRect \ TE needs a rect, not a bigRect. So we
- \ mirror our PanRect here.
-
- bool Wrap? \ Nov95 JRF
-
-
- private \ Housekeeping methods related to scrolling:
-
- :m DoScroll: \ ( dx dy -- ) This replaces PAN: in Scroller, except
- \ that dx and dy have their signs reversed
- \ (a pan down = a scroll up, etc.)
-
- ^viewRect: mainView call ClipRect
- scroll: theTE ;m
-
-
- :m PANRIGHT: { dx \ hs -- }
- get: theHscroll -> hs
- hs dx + get: Hpan >
- IF get: Hpan hs - -> dx THEN
- dx 0EXIT
- hs dx + dup put: theHscroll put: hpos
- dx negate 0 doScroll: self ;m
-
- :m PANLEFT: { dx \ hs -- }
- get: theHscroll -> hs hs 0EXIT
- hs dx - 0< IF hs -> dx THEN
- hs dx - dup put: theHscroll put: hpos
- dx 0 doScroll: self ;m
-
- :m PANDOWN: { dy \ vs -- }
- get: theVscroll -> vs
- vs dy + get: Vpan >
- IF get: Vpan vs - -> dy THEN
- dy 0EXIT
- vs dy + dup put: theVscroll put: vpos
- 0 dy negate doScroll: self ;m
-
- :m PANUP: { dy \ vs -- }
- get: theVscroll -> vs vs 0EXIT
- vs dy - 0< IF vs -> dy THEN
- dy 0EXIT
- vs dy - dup put: theVscroll put: vpos
- 0 dy doScroll: self ;m
-
-
- :m HPAGE: { \ left top rt bot -- #pixels }
- getViewRect: mainView -> bot -> rt -> top -> left
- rt left - get: Hunit - 0 max ;m
-
- :m VPAGE: { \ left top rt bot -- #pixels }
- getViewRect: mainView -> bot -> rt -> top -> left
- bot top - get: Vunit - 0 max ;m
-
- public
-
- :m WrapIt:
- true put: Wrap? ;m \ Nov95 JRF
-
- :m NoWrap:
- false put: Wrap? ;m \ Nov95 JRF
-
-
- \ The messages 1right: etc. are public because they're late-bound to.
-
- :m 1RIGHT: get: Hunit panRight: self noClip ;m
- :m 1LEFT: get: Hunit panLeft: self noClip ;m
- :m 1UP: get: Vunit panUp: self noClip ;m
- :m 1DOWN: get: Vunit panDown: self noClip ;m
-
- :m PGRIGHT: hPage: self panRight: self ;m
- :m PGLEFT: hPage: self panLeft: self ;m
- :m PGUP: vPage: self panUp: self ;m
- :m PGDOWN: vPage: self panDown: self ;m
-
-
- :m VDRAG: { \ dy vs -- }
- get: theVscroll -> vs
- vs get: Vpan >
- IF get: Vpan -> vs THEN \ Shouldn't really happen
- vs get: vpos - -> dy vs put: vpos
- 0 dy negate doScroll: self ;m
-
-
- :m HDRAG: { \ dx hs -- }
- get: theHscroll -> hs
- hs get: Hpan >
- IF get: Hpan -> hs THEN \ Shouldn't really happen
- hs get: hpos - -> dx hs put: hpos
- dx negate 0 doScroll: self ;m
-
-
- :m ?SCROLL: { x y \ l t r b -- } \ If necessary, scrolls so that the
- \ point (x, y) is in view.
- ^viewRect: mainView ->: tempRect
- get: Hunit get: Vunit inset: tempRect \ Trigger scrolling a bit before
- \ the boundary
- get: tempRect
- -> b -> r -> t -> l
- y b > IF y b - panDown: self THEN
- t y > IF t y - panUp: self THEN
- x r > IF x r - panRight: self THEN
- l x > IF l x - panLeft: self THEN ;m
-
-
- \ CoerceMainViewPanRect: is similar to CoercePanRect: mainView, except
- \ that we don't have child views to shift, but text to scroll instead.
-
- :m CoerceMainViewPanRect: { \ dx dy -- }
- (coercePanRect): mainView -> dy -> dx
- dx dy or 0EXIT
- dx dy doScroll: self
- getPanRect: mainView put: rPanRect ;m
-
-
- :m FIXPANRECT: { \ x y adr -- } \ Dec95 JRF revised to allow wrapping
-
- \ Ensures PanRect = TE's dest rect, plus a margin at the bottom and the
- \ left.
- handle: theTE @ -> adr
- get: Wrap?
- NIF
- 32766 getpoint: theTE -> y -> x
- y adr 4+ w! \ Adjust bottom of dest rect and
- 1600 adr 6 + w! \ right coordinate if not wrapping
-
- ELSE \ We can't be arbitrary here if wrapping
-
- adr 8 + size: rect drop 6 - adr 2 + w@ + adr 6 + w! \ adjust rt dest
- handle: theTE dup
- call TeCalText \ adjusts line ends so we can find new bottom,
- @ -> adr \ above call sometimes moves theTE, so
- \ dereference again
- size: theTE
- getpoint: theTE nip adr 4 + w! \ Adjust bottom of dest rect
- THEN
- adr ->: rPanRect
- getBotY: rPanRect bottomMargin + putBotY: rPanRect
- getTopX: rPanRect leftMargin - putTopX: rPanRect
- get: rPanRect putPanRect: mainView
- coerceMainViewPanRect: self \ Move it if it was out of kilter
- setPanRanges: self ;m \ Fix scroll bars
-
-
- :m MOVED: \ Note: we MUSTN'T call moved: super !!
- ^base moved: view \ but we must do the basic view stuff!
- get: alive? 0EXIT
- getViewRect: mainView setViewRect: theTE
- fixPanRect: self
- ^viewRect: mainView clear: rect
- ( update: self ) ;m
-
-
- \ Clicking is a little bit complicated. We can't handle clicking on the
- \ TE text via overriding CLICK: here, since the scroll bars are within
- \ our area as well. We could override CLICK: in MainView, which would
- \ mean defining a different MView subclass, or we could just install a
- \ suitable click handler in each MainView object instantiated. The latter
- \ is the easiest, so that's what we do. Then MainView has to call back
- \ this TEScroller object, since MainView doesn't know anything about
- \ thisTE. This sounds a little bit involved, but the code is very short,
- \ especially as a click on any Scroller (of which TEscroller is a subclass)
- \ puts its own address in ClickedScroller. This makes it easy for MainView
- \ to send a message back. The other nice thing is that we KNOW that this
- \ click handler will only be called when we want it - we don't need to filter
- \ out clicks on scroll bars or anywhere else. MainView's click handler
- \ simply never sees them.
-
-
- :m AUTOSCROLL: \ Called from DragProc.
- get: theMouse drop
- ?scroll: self ;m
-
-
- :proc DRAGPROC \ ( TEhandle newPoint -- )
- \ See, we CAN define a :proc word (or any other) in the
- \ middle of a class definition!
- autoScroll: [ clickedScroller ]
- word0 drop w 1 \ We have to return a Pascal boolean TRUE!
-
- ;proc
-
-
- :m MVCLICKED: \ Called from MainView via its click handler (see just below).
- \ We just have to set theTE's dragproc and call its
- \ click: method.
-
- ['] dragproc ptr: theTE 42 + ! \ Set drag proc in TE record
- click: theTE ;m
-
-
- : DoClick \ This word is installed as MainView's click handler.
- \ It will ONLY be called when there's a click on MainView
- \ - not for a scroll bar click.
-
- MVclicked: [ clickedScroller ] ;
-
-
-
- :m SIZE: \ ( -- n )
- size: theTE ;m
-
-
- :m ENABLE:
- enable: super
- activate: theTE ;m
-
- :m DISABLE:
- disable: super
- deactivate: theTE ;m
-
-
- :m DRAW:
- \ TE looks after clipping itself, so we don't need our default clipping.
- \ It would cause problems anyway, since we use the grafport origin when
- \ calling TE, while our default clipping uses view origin. So we
- \ disable our own clipping.
-
- false put: setClip?
- noClip \ Experimentation shows this is definitely necessary!!
- addr: viewRect dup call eraserect update: theTE ;m
- \ Added EraseRect to fix a caret problem
- \ using outline hilite feature - Nov 95, JRF
-
- :m SETSELECT: { strt end -- }
- pushPort set: [ get: ^myWind ]
- strt end select: theTE
- \ update: [ get: ^myWind ]
- popPort ;m
-
-
- :m CARETLOC: \ ( -- x y )
- selstart: theTE
- getpoint: theTE ;m
-
- :m CARETINTOVIEW: \ Scrolls if nec to get the insertion point visible
- caretLoc: self ?scroll: self
- noClip ;m \ not quite sure why we need this, but we do!
-
-
- :m KEY: { char -- }
- noClip \ it seems we can sometimes be clipped out
- char key: theTE
- selStart: theTE selEnd: theTE <>
- char 8 ( delete ) = or
- char RET = or
- get: Wrap? or \ Dec95 JRF
- IF fixPanRect: self THEN \ If insertion/deletion may have
- \ changed BoundsRect
- caretIntoView: self \ Scroll if necessary
- ;m
-
- :m INSERT: \ ( addr len )
- noClip \ it seems we can sometimes be clipped out
- insert: theTE
- fixPanRect: self \ insertion may have
- \ changed BoundsRect
- caretIntoView: self \ Scroll if necessary
- ;m
-
- :m $INSERT: ( str -- ) { \ adr -- }
- -> $tmp
- get: $tmp insert: self ;m
-
-
- :m NEW:
- new: super
- get: viewRect putPanRect: mainView \ to start with, anyway
- addr: viewRect ->: rPanRect
- ['] doClick setClick: mainview \ Install mainview click hndlr
- addr: rPanRect ^viewRect: mainview new: theTE
- get: Wrap? IF WrapIt: theTE ELSE NoWrap: theTE THEN \ Dec95 JRF
- fixPanRect: self
- 10 panLeft: self \ Ensure fully scrolled left initially
- ;m
-
-
- :m CUT: cut: theTE ;m
-
- :m COPY: copy: theTE ;m
-
- :m PASTE: paste: theTE ;m
-
- :m CLEAR: clear: theTE ;m
-
- :m TextHandle: textHandle: theTE ;m
-
-
- :m GETSELECT: \ ( -- addr len ) \ return hilited selection
- getselect: theTE ;m
-
- \ getline: will return the entire line in which the cursor is currently in,
- \ regardless of where in the line the cursor is located. No text need be
- \ selected.
-
- :m GETLINE: \ ( -- addr len )
- getline: theTE ;m
-
- :m RELEASE:
- release: theTE ;m
-
- :m HANDLE: \ ( -- TEhndl )
- handle: theTE ;m
-
- :m SELEND: \ ( -- n )
- selend: theTE ;m
-
- :m SELSTART: \ ( -- n )
- selstart: theTE ;m
-
- :m LINEEND: \ ( -- n ) \ **
- lineEnd: theTE ;m
-
- :m IDLE:
- idle: super
- mouseHere?: mainView IF ibeamcurs ELSE arrowCurs THEN
- idle: theTE ;m
-
-
- :m dump:
- dump: theTE ;m
-
-
- :m CLASSINIT: \ Note here that we inset the left margin of mainView by
- \ 4 pixels - it looks better there than right on the
- \ edge.
-
- \ 4 0 0 0 setBounds: mainView
- classinit: super
- 16 dup put: Hunit put: Vunit ;m
-
- ;class
-